package com.woniuxy.meal.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.woniuxy.meal.common.RedisKey;
import com.woniuxy.meal.entity.User;
import com.woniuxy.meal.dao.UserMapper;
import com.woniuxy.meal.exception.userException.UserException;
import com.woniuxy.meal.exception.userException.UserExceptionCode;
import com.woniuxy.meal.form.ModifyInfoForm;
import com.woniuxy.meal.form.RegisterForm;
import com.woniuxy.meal.form.UserLoginForm;
import com.woniuxy.meal.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniuxy.meal.util.*;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author zz
 * @since 2023年06月13日
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private OSSUtil ossUtil;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private UploadFileUtil uploadFileUtil;

    /**
     * 用户登录
     * @param form
     * @return
     * @throws Exception
     */
    @Override
    public User login(UserLoginForm form) throws Exception{
        User user = new User();
        if (form.getUserPhone()!=null&&!form.getUserPhone().equals("")){
            String saveCode = redisUtil.getString(RedisKey.getSendRegCodeKey(form.getUserPhone()));
            if (!form.getCode().equals(saveCode)) {
                throw new UserException(UserExceptionCode.USER_CODE_ERROR);
            }
            QueryWrapper<User> wrapper = new QueryWrapper<>();
            wrapper.eq("userPhone", form.getUserPhone());
            user = userMapper.selectOne(wrapper);
            if (user == null) {
                throw new UserException(UserExceptionCode.USER_PHONE_ERROR);
            }
            redisUtil.delete(RedisKey.getSendRegCodeKey(form.getUserPhone()));
        }
        else {
            QueryWrapper<User> queryWrapper = new QueryWrapper();
            queryWrapper.eq("email", form.getEmail());
            user = userMapper.selectOne(queryWrapper);
            if(user==null){
                throw new UserException(UserExceptionCode.USER_NOT_REGISTER);
            }
            if (!user.getUserPassword().equals(form.getUserPassword())) {
                if (redisUtil.exist(RedisKey.getInputPwdInHourKey(form.getEmail())) && Integer.parseInt(redisUtil.getString(RedisKey.getInputPwdInHourKey(form.getEmail()))) == 3){
                    throw new UserException(UserExceptionCode.USER_PASSWORD_ERROR);
                }
                if (!redisUtil.exist(RedisKey.getInputPwdInHourKey(form.getEmail()))) {
                    redisUtil.setString(RedisKey.getInputPwdInHourKey(form.getEmail()), "1", 3600);
                } else {
                    redisUtil.incr(RedisKey.getInputPwdInHourKey(form.getEmail()));
                }
                throw new UserException(UserExceptionCode.USER_PASSWORD_NOT_MATCH);
            }
        }
        return user;
    }

    /**
     * 发送验证码
     * @param phone
     * @throws Exception
     */
    @Override
    public void sentCode(String phone) throws Exception {

        if (redisUtil.exist(RedisKey.getSendRegCodeInMinKey(phone))) {
            throw new Exception("验证码已发送，请勿重复发送");
        }
        if (redisUtil.exist(RedisKey.getSendRegCodeInHourKey(phone)) && Integer.parseInt(redisUtil.getString(RedisKey.getSendRegCodeInHourKey(phone))) == 5) {
            throw new Exception("一个小时内最多只能发送5次验证码");
        }

//        String code = SMSUtil.send(phone);
        String code = "55667";
        redisUtil.setString(RedisKey.getSendRegCodeKey(phone), code, 300);
        redisUtil.setString(RedisKey.getSendRegCodeInMinKey(phone), "1", 60);
        if (!redisUtil.exist(RedisKey.getSendRegCodeInHourKey(phone))) {
            redisUtil.setString(RedisKey.getSendRegCodeInHourKey(phone), "1", 3600);
        } else {
            redisUtil.incr(RedisKey.getSendRegCodeInHourKey(phone));
        }


    }


    /**
     * 新用户注册
     * @param form
     * @throws Exception
     */
    @Override
    @Transactional
    public void registerUser(RegisterForm form) throws Exception{
        RLock phoneLock = redissonClient.getFairLock(RedisKey.getPhoneKey(form.getUserPhone().toString()));
        RLock emailLock = redissonClient.getFairLock(RedisKey.getEmailKey(form.getEmail()));
        RLock lock = redissonClient.getMultiLock(phoneLock, emailLock);
        try {
            boolean success = lock.tryLock(20, TimeUnit.SECONDS);
            if (success) {
                QueryWrapper<User> userInfoQueryWrapper = new QueryWrapper<>();
                userInfoQueryWrapper.eq("userPhone", form.getUserPhone()).or().eq("email", form.getEmail());
                User user = userMapper.selectOne(userInfoQueryWrapper);
                if (user != null) {
                    throw new UserException(UserExceptionCode.USER_EXIST);
                }
                User user1 = BeanUtil.toBean(form, User.class);
                userMapper.insert(user1);
            } else {
                throw new Exception("服务器繁忙");
            }

        } finally {
            if (phoneLock.isLocked() && emailLock.isLocked()) {
                lock.unlock();
            }

        }

    }

    /**
     * 修改头像
     * @param file
     * @param userId
     * @throws Exception
     */
    @Override
    public void upPhoto(MultipartFile file, Integer userId) throws Exception {
        String url = uploadFileUtil.uploadImg(file);
        User user = getById(userId);
        String userImg = user.getUserImg();
        if (userImg!=null){
            String name = userImg.substring(userImg.lastIndexOf("/"));
            ossUtil.deleteFile("bucket-book-fjx",name.substring(1));
        }
        user.setUserImg(url);
        updateById(user);

    }

    /**
     * 修改用户信息
     * @param form
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public User modifyInfo(ModifyInfoForm form) throws Exception {
        String token = WebUtil.getRequest().getHeader("token");
        Long userId = redisUtil.getUserIdByToken(token);
        User user = getById(userId);
        if (user==null){
            throw new UserException(UserExceptionCode.USER_NOT_LOGIN);
        }

        if (form.getUserName()!=null){
            user.setUserName(form.getUserName());
        }
        if (form.getEmail()!=null){
            user.setEmail(form.getEmail());
        }
        if (form.getUserPhone()!=null){
            String saveCode = redisUtil.getString(RedisKey.getSendRegCodeKey(user.getUserPhone().toString()));
            if (!form.getCode().equals(saveCode)) {
                throw new UserException(UserExceptionCode.USER_CODE_ERROR);
            }
            redisUtil.delete(RedisKey.getSendRegCodeKey(user.getUserPhone().toString()));
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("userPhone",form.getUserPhone());
            User user1 = userMapper.selectOne(queryWrapper);
            if (user1!=null){
                throw new UserException(UserExceptionCode.USER_EXIST);
            }
            user.setUserPhone(form.getUserPhone());
        }
        if (form.getUserPassword()!=null){
            String oldPwd = form.getOldPassword();
            if (!user.getUserPassword().equals(oldPwd)){
                throw new UserException(UserExceptionCode.USER_PASSWORD_NOT_MATCH);
            }
            user.setUserPassword(form.getUserPassword());
        }
        updateById(user);
        return user;
    }



}
